package org.spring.boot.example.dds;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.config.BeanDefinition;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.beans.factory.config.RuntimeBeanReference;
import org.springframework.beans.factory.support.BeanDefinitionRegistry;
import org.springframework.beans.factory.support.BeanDefinitionRegistryPostProcessor;
import org.springframework.beans.factory.support.GenericBeanDefinition;
import org.springframework.context.annotation.ImportBeanDefinitionRegistrar;
import org.springframework.core.type.AnnotationMetadata;

public class DynamicDataSourceAdvisorCreator implements BeanDefinitionRegistryPostProcessor, ImportBeanDefinitionRegistrar {

	private final static String ADVISOR_BEAN_NAME = DynamicDataSourceAdvisor.class.getName();
	private final static String ADVICE_BEAN_NAME = DynamicDataSourceAdvice.class.getName();
	private final static String POINTCUT_BEAN_NAME = DynamicDataSourcePointcut.class.getName();
	
	private boolean isLoad;
	@Override
	public void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) throws BeansException {

	}

	@Override
	public void postProcessBeanDefinitionRegistry(BeanDefinitionRegistry registry) throws BeansException {
		if (isLoad || registry.containsBeanDefinition(ADVISOR_BEAN_NAME)) {
			return;
		}
		GenericBeanDefinition advisorDef = new GenericBeanDefinition();
		advisorDef.setBeanClass(DynamicDataSourceAdvisor.class);
		advisorDef.setBeanClassName(ADVISOR_BEAN_NAME);
		advisorDef.setRole(BeanDefinition.ROLE_INFRASTRUCTURE);

		if (registry.containsBeanDefinition(ADVICE_BEAN_NAME)) {
			advisorDef.getPropertyValues().add("advice", new RuntimeBeanReference(ADVICE_BEAN_NAME));
		} else {
			advisorDef.getPropertyValues().add("advice", new DynamicDataSourceAdvice());
		}

		if (registry.containsBeanDefinition(POINTCUT_BEAN_NAME)) {
			advisorDef.getPropertyValues().add("pointcut", new RuntimeBeanReference(POINTCUT_BEAN_NAME));
		} else {
			advisorDef.getPropertyValues().add("pointcut", new DynamicDataSourcePointcut());
		}

		registry.registerBeanDefinition(ADVISOR_BEAN_NAME, advisorDef);
		isLoad = true;
	}

	@Override
	public void registerBeanDefinitions(AnnotationMetadata importingClassMetadata, BeanDefinitionRegistry registry) {
		if(isLoad) {
			return;
		}
		postProcessBeanDefinitionRegistry(registry);
		isLoad = true;
	}

}
